package com.fecean.aabbc.netty.dispatcher7;

import com.fecean.aabbc.netty.handler7.NettyResponseChannelHandler;
import com.fecean.aabbc.netty.message7.ResponseMessage;
import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 ** 响应结果监听类，用于返回请求响应结果
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-03-13 13:37
 * @blame Team
 */
@Slf4j
public class ResponseFuture implements Future<ResponseMessage> {

    /**
     ** 因为请求和响应是一一对应的，因此初始化CountDownLatch值为1。
     */
    private CountDownLatch countDownLatch = new CountDownLatch(1);

    /**
     ** Future的请求时间，用于计算Future是否超时
     */
    private long beginTimeMilli = Instant.now().toEpochMilli();

    /**
     ** 响应超时时间，单位为毫秒，生产环境应用使用配置参数传入
     */
    private static final long RESPONSE_TIMEOUT_MILLI = 60_000;

    /**
     ** 响应通道处理
     */
    private NettyResponseChannelHandler responseHandler;

    /**
     ** 需要响应线程设置的响应结果
     */
    private ResponseMessage response;

    /**
     ** 无参数构造方法
     */
    private ResponseFuture(){
        throw new IllegalArgumentException("未实现无参数构造方法，请使用有参数的构造方法");
    }

    /**
     ** 构造方法，在NettyResponseChannelHandler类上进行注册当前响应结果监听类
     *
     * @param responseHandler 响应通道处理
     */
    public ResponseFuture(NettyResponseChannelHandler responseHandler){
        this.responseHandler = responseHandler;
    }

    /**
     ** 取消，未实现处理，默认为false
     *
     * @param mayInterruptIfRunning 是否中断正在运行的线程
     * @return false
     */
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return false;
    }

    /**
     ** 是否取消，未实现处理，默认为false
     *
     * @return false
     */
    @Override
    public boolean isCancelled() {
        return false;
    }

    /**
     ** 是否完成
     *
     * @return 如果存在响应结果则返回true，否则返回false
     */
    @Override
    public boolean isDone() {
        return response != null;
    }

    /**
     ** 等待获取结果
     *
     * @return 响应结果
     */
    @Override
    public ResponseMessage get() {
        return get(RESPONSE_TIMEOUT_MILLI, TimeUnit.MILLISECONDS);
    }

    /**
     ** 等待获取结果
     *
     * @param timeout 超时时间值
     * @param unit 超时时间单位
     * @return 响应结果
     */
    @Override
    public ResponseMessage get(long timeout, TimeUnit unit) {
        try {
            if(countDownLatch.await(timeout, unit)){
                return this.response;
            }
        } catch (InterruptedException e) {
            log.error("", e);
        }
        return null;
    }

    /**
     ** 接收响应结果，并让计数器减一
     *
     * @param response 响应结果
     */
    public void received(ResponseMessage response) {
        this.response = response;
        countDownLatch.countDown();
    }

    /**
     ** 获取请求开始时间的毫秒数
     *
     * @return 请求开始时间的毫秒数
     */
    public long getBeginTimeMilli() {
        return beginTimeMilli;
    }
}
